#include "UndoProcess.h"

UndoProcess::UndoProcess(string cmdString,allTaskList *givenLists,allCommandStack *givenStacks,int time):LogicProcess(cmdString,givenLists,givenStacks){
	needList=&allTask->getUpcomingTasks();
	times=time;
	needCommandStack=&prevCmds->getUndoCmds();

}

bool UndoProcess::canRestore(){
	bool result;
	result= times <= needCommandStack->getLength();
	return result;
}

void UndoProcess::HandleProcesss(){
	CommandPackage prevPackage;

	if (canRestore())
		for (int i=0;i<times;i++){
			do {
				prevPackage=getNearestPackage();
				RestoreCommand(prevPackage);
				backUpToRedo(prevPackage);
			}
			while(prevPackage.StillNeedProcess()==true);
		}
	
	fromNeedtoDisplay();
}

CommandPackage UndoProcess::getNearestPackage(){
	CommandPackage tmp;
	needCommandStack->pop(tmp);
	//prevCmds->getUndoCmds().pop(tmp);
	
	return tmp;
}

void UndoProcess::RestoreCommand(CommandPackage Package){

	Task prevTask=Package.getTask();

	commandType prevCmd=Package.getType();

	taskContainer rightList=Package.getTaskContainer();

	RestoreByCommandType(prevTask,prevCmd,rightList);
}

void UndoProcess::RestoreByCommandType(Task task,commandType cmdType,taskContainer rightList){

	LogicProcess *miniProcessor;
	TaskList *need=getNeedList(rightList);
	switch(cmdType){
	case Add:
		miniProcessor=new AddProcess(task,need);
		break;
	case Delete:
		miniProcessor=new DeleteProcess(task,need);
		break;
	}

	miniProcessor->quickProcess(task);
	delete miniProcessor;
}

//Decode the taskcontainer to get the right list
TaskList* UndoProcess::getNeedList(taskContainer container){
	TaskList *tmp;
	switch(container){
	case upcoming:
		tmp=&allTask->getUpcomingTasks();
		break;
	case deleted:
		tmp=&allTask->getDeletedTasks();
		break;
	case finished:
		tmp=&allTask->getFinishedTasks();
		break;
	default:
		break;
	}
	return tmp;
}

void UndoProcess::backUpToRedo(CommandPackage currentPackage){
	CommandPackage redoPackage=convertToRedoPackage(currentPackage);
	prevCmds->getExecutedCmds().push(redoPackage);
}

CommandPackage UndoProcess::convertToRedoPackage(CommandPackage currentPackage){
	CommandPackage tmp;
	tmp.setTask(currentPackage.getTask());

	commandType type=convertCommand(currentPackage.getType());
	tmp.setType(type);

	tmp.setContainer(currentPackage.getTaskContainer());
	tmp.setNeedProcessMore(currentPackage.StillNeedProcess());

	return tmp;
}

commandType UndoProcess::convertCommand(commandType type){
	commandType tmpType;
	//The command type for undo or redo is only add or delete
	if (type==Add)
		tmpType=Delete;
	else
		tmpType=Add;

	return tmpType;
}

